﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace CoolCode.Controls
{
   public delegate void PageIndexChange(int pageIndex);
    
    public class VisualPager : Control
    {
        public int SectionPages { get; set; }
        public int PageCount { get; set; }
        public Color BlockBorderBrush { get; set; }
        public double BlockSize { get; set; }
        public PageIndexChange OnPageIndexChange { get; set; }
             
        public VisualPager()
            : base()
		{
            this.DefaultStyleKey = typeof(VisualPager);
            this.PageCount = 35;
            this.SectionPages = 10;
            this.BlockBorderBrush = Colors.Orange;
            this.BlockSize = 24;
		}

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

            this.sectionCount = this.PageCount / this.SectionPages + 1;
            
            this.block = this.GetTemplateChild("block") as Border;
            this.block.Height = this.block.Width = BlockSize;
            this.block.BorderBrush = new SolidColorBrush(this.BlockBorderBrush);
            
            this.numbersCanvas = this.GetTemplateChild("numbersCanvas") as Canvas;

            if (this.sectionCount > 1)
                numbersCanvas.Width = this.SectionPages * this.BlockSize;
            else
                numbersCanvas.Width = this.PageCount * this.BlockSize;

            numbersCanvas.Height = this.BlockSize;
            numbersCanvas.Clip = new RectangleGeometry() { Rect = new Rect(0, -2, numbersCanvas.Width, numbersCanvas.Height + 2) };

            this.numbersPanel = this.GetTemplateChild("numbersPanel") as StackPanel;
            for (int i = 1; i <= PageCount; i++)
            {
                TextBlock num = new TextBlock();
                num.Width = this.BlockSize;
                num.Height = this.BlockSize;
                num.FontSize = 13;
                num.Tag = i;
                num.TextAlignment = TextAlignment.Center;
                num.Text = i.ToString();
                num.MouseLeftButtonDown += new MouseButtonEventHandler(num_MouseLeftButtonDown);

                numbersPanel.Children.Add(num);
            }

            this.first = this.GetTemplateChild("first") as Button;
            first.Click += new RoutedEventHandler(first_Click);

            this.pre = this.GetTemplateChild("pre") as Button;
            pre.Click += new RoutedEventHandler(pre_Click);

            this.next = this.GetTemplateChild("next") as Button;
            next.Click += new RoutedEventHandler(next_Click);

            this.last = this.GetTemplateChild("last") as Button;
            last.Click += new RoutedEventHandler(last_Click);

            this.storyboard = this.GetTemplateChild("storyboard") as Storyboard;
            this.animation1 = this.storyboard.Children[0] as DoubleAnimation;
            this.animation2 = this.storyboard.Children[1] as DoubleAnimation;

            this.position = this.GetTemplateChild("position") as TextBlock;

            this.SetLeftEnable(false);

            if (this.sectionCount == 1)
                this.SetRightEnable(false);

            this.SetPositionText("1");

		}


        void last_Click(object sender, RoutedEventArgs e)
        {
            this.currentSection = this.sectionCount;
            this.animation1.To = -this.numbersCanvas.Width * (currentSection - 1);
            this.animation2.To = -this.BlockSize;
            this.storyboard.Begin();

            this.SetLeftEnable(true);
            this.SetRightEnable(false);
        }

        void next_Click(object sender, RoutedEventArgs e)
        {
            if (currentSection == this.sectionCount)
                return;

            this.animation1.To = -this.numbersCanvas.Width * currentSection;
            this.animation2.To = -this.BlockSize;
            this.storyboard.Begin();

            this.currentSection++;

            this.SetLeftEnable(true);
            if (currentSection == this.sectionCount)
                this.SetRightEnable(false);
        }

        void first_Click(object sender, RoutedEventArgs e)
        {
            this.currentSection = 1;
            this.animation1.To = 0;
            this.animation2.To = -this.BlockSize;
            this.storyboard.Begin();

            this.SetLeftEnable(false);
            this.SetRightEnable(true);
        }

        void pre_Click(object sender, RoutedEventArgs e)
        {
            if (this.currentSection == 1)
                return;

            this.animation1.To = - this.numbersCanvas.Width * (currentSection - 2);
            this.animation2.To = -this.BlockSize;
            this.storyboard.Begin();

            this.currentSection--;

            this.SetRightEnable(true);
            if (currentSection == 1)
                this.SetLeftEnable(false);
        }

        void num_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FrameworkElement fe = sender as FrameworkElement;
            int num = Convert.ToInt16(fe.Tag);

            this.animation2.To = (num - 1) % SectionPages * this.BlockSize;
            this.storyboard.Begin();

            this.SetPositionText(fe.Tag.ToString());

            this.PageIndexChange(num);
        }

        void PageIndexChange(int pageIndex)
        {
            if (this.OnPageIndexChange != null)
                OnPageIndexChange(pageIndex);
        }

        void SetLeftEnable(bool enable)
        {           
            if (!enable)
                this.first.Opacity = this.pre.Opacity = 0;
            else
                this.first.Opacity = this.pre.Opacity = 1;           
        }

        void SetRightEnable(bool enable)
        {          
            if (!enable)
                this.last.Opacity = this.next.Opacity = 0;
            else
                this.last.Opacity = this.next.Opacity = 1;           
        }

        void SetPositionText(string page)
        {
            this.position.Text = string.Format("{0}/{1}",  page, this.PageCount);
            this.position.Opacity = 0.5;

        }

        private int sectionCount;
        private int currentSection = 1;

        private StackPanel numbersPanel;
        private Border block;       
        private Storyboard storyboard;
        private DoubleAnimation animation1;
        private DoubleAnimation animation2;
        private Canvas numbersCanvas;
        private Button first;
        private Button pre;
        private Button next;
        private Button last;
        private TextBlock position;
    }
}
